home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
cpp_libs
/
utility.lha
/
utility
/
listiter.H
< prev
next >
Wrap
C/C++ Source or Header
|
1993-08-08
|
5KB
|
165 lines
#ifndef LISTITER_H
#define LISTITER_H
// This is a generic list iterator. An iterator will sequentially go through
// each element of the associated list, starting with the first element. It is
// also possible to explicitly rewind the iterator, or to move forward or
// backward in the list.
//
// This is a protected class, i.e., it is not possible to create instances
// of it. Derived classes provide iterators for specific types of lists.
// First, a new iterator type must be declared, for example, for
// a list of integers:
//
// ITERATOR_DECLARE(int);
//
// This declares a new class, called `intIterator'.
// Iterator types should only be declared once.
// After that, iterators of this type can be declared as needed:
//
// ITERATOR(int) it(list);
//
// and used like this:
//
// .nf
// int* p;
// while( (p = it()) != nil)
// /* something */;
// .fi
//
// To make the use of iterators easier, some macros have defined for the
// most common forms.
//
// .SS dolist(var,list,type)
// .SS enddo
// The dolist-enddo construct defines a reference variable `var', an
// iterator `var_iter', and iterates through all the elements of the
// list. For example:
//
// .nf
// dolist(p,list,int)
// cout << p;
// p_iter.Skip(1);
// enddo;
//
// will print every second element of the list.
//
// .SS maplist(func,list,type)
// Maplist can be used when a single function should be invoked on every element
// of the list. The function `func' should be of type "void func(type)", or
// "void func(type &)".
// Example:
//
// maplist(f,list,int);
//
// Maplist is similar to `mapc' in Common LISP.
//
// .SS filterlist(src,expr,dst,type)
// Filterlist will iterate trough the source list `src' and insert all
// elements for which the condition `expr' is true into the destination
// list `dst'. Example:
//
// filterlist(all,e == "x",xlist,String);
//
// The expression should return a boolean value; the name `e' denotes the
// current list element in the expression. Note that the destination list
// is not automatically cleared before use. Element order is not preserved!
//
// .SS printlist(ostream&,list,type,sep)
// Printlist will print all elements of the list on the stream. Each element
// will be followed by the given separator. Example:
//
// printlist(cout,l,String,"\n");
//
// .SS Caveats
// DO NOT INSERT OR REMOVE ELEMENTS IN THE ITERATED LIST! This will result
// in elements being skipped or iterated several times. An alternative is to
// move designated elements to a temporary list, and then Remove() all
// members of the second list from the first list.
//
// DO NOT USE BLANKS WHEN CALLING MACROS! White space is preserved in macros
// and will cause compilation errors with dolist and maplist. For example,
// "maplist(func, list, int)" will fail.
//
// .SS Author
// Dag Bruck, Department of Automatic Control, Lund Institute of Technology,
// Box 118, S-221 00 Lund, Sweden (dag@control.lth.se).
//
// $Id: listiter.H,v 1.4 91/09/06 16:58:03 dag Exp $
#include <defs.H>
#include <list.H>
class GenericIterator {
protected:
GenericIterator(const GenericList &);
// Create iterator, starting at first element.
public:
Pointer operator () ();
// Returns next element in list, or nil at end of list.
void Rewind();
// Rewinds iterator to first element of list.
void Skip(int di);
// Move iterator forward or backward. The iterator will never
// move before the first element.
private:
const GenericList& l;
unsigned i;
};
#define ITERATOR(type)NAME2(type,Iterator)
#define ITERATOR_DECLARE(type)ITERATOR_DECLARE2(ITERATOR(type),type)
#define ITERATOR_DECLARE2(__name,type)class __name : public GenericIterator { \
public: \
__name(const LIST(type)& list) : GenericIterator(list) {} \
type* operator () () { return (type *) GenericIterator::operator () (); } \
}
#define CONSTITERATOR(type)NAME2(NAME2(const_,type),Iterator)
#define CONSTITERATOR_DECLARE(type)CONSTITERATOR_DECLARE2(CONSTITERATOR(type),type)
#define CONSTITERATOR_DECLARE2(__name,type)class __name : public GenericIterator { \
public: \
__name(const CONSTLIST(type)& list) : GenericIterator((const LIST(type)&) list) {} \
const type* operator () () { return (const type *) GenericIterator::operator () (); } \
}
#define dolist(var,list,type) do { \
ITERATOR(type) NAME2(var,_iter)(list);\
while (true) { \
register type& var = *NAME2(var,_iter)(); if (&var == nil) break;
#define doconstlist(var,list,type) do { \
CONSTITERATOR(type) NAME2(var,_iter)(list);\
while (true) { \
register const type& var = *NAME2(var,_iter)(); if (&var == nil) break;
#define enddo }} while (false)
#define maplist(func,list,type) dolist(_p,list,type) func(_p); enddo
#define mapconstlist(func,list,type) doconstlist(_p,list,type) func(_p); enddo
#define filterlist(src,expr,dst,type) dolist(e,src,type) if(expr)dst+=e; enddo
#define filterconstlist(src,expr,dst,type) doconstlist(e,src,type) if(expr)dst+=e; enddo
#define printlist(ostr,l,type,sep) dolist(e,l,type) ostr << e << sep; enddo
#define printconstlist(ostr,l,type,sep) doconstlist(e,l,type) ostr << e << sep; enddo
inline GenericIterator :: GenericIterator(const GenericList& li)
: l(li), i(0)
{ }
inline Pointer GenericIterator :: operator () ()
{
register unsigned n = l.n;
return i >= n ? nil : l.p[n - i++ - 1];
}
#endif